package com.duofan.gmall.search.thread;

import java.util.concurrent.*;

public class ThreadTest {
    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
//        System.out.println("main start...");
/*        CompletableFuture.runAsync(() -> {
            System.out.println("当前线程: " + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果: " + i);
        }, executor);*/

//        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程: " + Thread.currentThread().getId());
//            int i = 10 / 2;
////            int i = 10 / 0;
//            System.out.println("运行结果: " + i);
//            return i;
//        }, executor).handle((res, thr) -> {
//            if(res != null) {
//                return res * 2;
//            }
//            if(thr != null) {
//                return 0;
//            }
//            return 0;
//        }); // 方法完成后的处理
        /*.whenComplete((res, err) -> { // 可以得到异常,无法修改结果
            System.out.println("异步任务完成..., 结果是: " + res + " 异常是: " + err);
        }).exceptionally(t -> {
            return 10; // 感知异常,返回默认值
        });*/
//        Integer i = future.get();
//        System.out.println("supplyAsync result: " + i);

        /**
         * 串行化
         * 1.thenRun,不能获取上一步执行结果
         * 2.thenAcceptAsync,能获取结果,无返回值
         */
//        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
//            System.out.println("当前线程: " + Thread.currentThread().getId());
//            int i = 10 / 2;
////            int i = 10 / 0;
//            System.out.println("运行结果: " + i);
//            return i;
//        }, executor).thenApplyAsync(res -> {
//            System.out.println("任务2启动..." + res);
//            return "Hello" + res;
//        }, executor);
//                .thenAcceptAsync(res -> {
//                    System.out.println("任务2启动..." + res);
//                }, executor);

//                .thenRunAsync(() -> {
        //            System.out.println("任务2启动...");
        //        }, executor);

        System.out.println("main start...");
//        CompletableFuture<Object> futureA = CompletableFuture.supplyAsync(() -> {
//            System.out.println("任务1开始...");
//            int i = 10 / 2;
//            System.out.println("任务1结束...");
//            return i;
//        }, executor);
//
//        CompletableFuture<Object> futureB = CompletableFuture.supplyAsync(() -> {
//            System.out.println("任务2开始...");
//            try {
//                Thread.sleep(3000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            System.out.println("任务2结束...");
//            return "hello";
//        }, executor);

//        futureA.runAfterBothAsync(futureB, () -> {
//            System.out.println("任务3开始...");
//        } ,executor);

        // 接收参数
//        futureA.thenAcceptBothAsync(futureB, (f1, f2) -> {
//            System.out.println("任务3开始...之前的结果" + f1 + ", " + f2);
//        }, executor);

        // 带返回值
//        CompletableFuture<String> future = futureA.thenCombineAsync(futureB, (f1, f2) -> {
//            return f1 + ", " + f2;
//        }, executor);
//        System.out.println("任务3结果: " + future.get());
//
//        futureA.runAfterEitherAsync(futureB, () -> {
//            System.out.println("任务3结束...");
//        } ,executor);

        // 接收结果,无返回值
//        futureA.acceptEitherAsync(futureB, (res) -> {
//            System.out.println("任务3结束...结果:" + res);
//        }, executor);
//        System.out.println("main end..." );

        // 接收结果,有返回值
//        CompletableFuture<String> future = futureA.applyToEitherAsync(futureB, (res) -> {
//            return res.toString() + "哈哈";
//        }, executor);
//        System.out.println("任务3结果: " + future.get());

        CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品图片信息...");
            return "hello.jpg";
        });
        CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品属性信息...");
            return "黑色+256G";
        });
        CompletableFuture<String> futureC = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("查询商品介绍...");
            return "华为";
        });
        // 方式1
        // futureA.get();futureB.get();futureC.get(); // 阻塞,效率低
        // 方式2 allOf
//        CompletableFuture<Void> allOf = CompletableFuture.allOf(futureA, futureB, futureC);
//        allOf.get(); // 等待所有结果完成
//        System.out.println("所有结果: " + futureA.get() + ", " + futureB.get() + ", " + futureC.get());

        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(futureA, futureB, futureC);
        System.out.println("任一结果: " + anyOf.get());
        System.out.println("main end..." );
    }

    public static void thread(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main start...");
        // 1 继承Thread类
//        ThreadA threadA = new ThreadA();
//        threadA.start();

        // 2 实现Runnable接口
//        RunnableA runnableA = new RunnableA();
//        new Thread(runnableA).start();

        // 3 实现Callable接口
        // 分析代码可知,FutureTask也可传Runnable,并用另一个对象接收返回值
//        FutureTask<Integer> futureTask = new FutureTask<>(new CallableA());
//        new Thread(futureTask).start();
//        // 阻塞等待
//        Integer res = futureTask.get();
//        System.out.println("callable result: " + res);

        // 以上3种启动线程方式都不用(耗尽资源)
        // 所有的多线程异步任务都交给线程池

        // 4 线程池
        // 固定数量的线程池,当前系统池只有一两个,每个异步任务直接提交给线程池
//        service.execute(new RunnableA());

        /**
         * 原生创建线程池
         * 七大参数
         * @param corePoolSize 核心线程数,线程池创建好就准备就绪的线程数
         * @param maximumPoolSize 最大线程数
         * @param keepAliveTime 当前线程数大于核心线程数,空闲线程的存活时间
         * @param unit keepAliveTime的时间单位
         * @param workQueue 任务执行前的保存队列
         * @param threadFactory executor创建线程使用的工厂
         * @param handler 队列已满拒绝执行策略
         *
         * 执行流程:
         * 1.准备核心线程接收任务
         *   1.1 core满,进入阻塞队列
         *   1.2 队列满,开新线程,最多max
         *   1.3 max满,拒绝任务
         *   1.4 max执行完成,在keepAliveTime释放多于core的任务
         *   LinkedBlockingDeque默认是Integer最大值,耗尽资源,压测后定数目
         *   defaultThreadFactory默认的线程工厂
         *   AbortPolicy默认拒绝策略,丢弃
         *
         * 面试题:
         * 一个线程池,core 7,max 20, queue 50, 100并发如何分配
         * 7个立即执行,50个进入队列,再开13个执行,30个使用拒绝策略(一般丢弃)
         * 如不想抛弃,可以使用CallerRunsPolicy同步执行
         */
//        ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
//                200,
//                10,
//                TimeUnit.SECONDS,
//                new LinkedBlockingDeque<>(100000),
//                Executors.defaultThreadFactory(),
//                new ThreadPoolExecutor.AbortPolicy());
        // 常用的几种线程池
        // core 0,所有都可回收
//        Executors.newCachedThreadPool();
        // 固定大小,core max都是50
//        Executors.newFixedThreadPool(50);
        // 定时任务线程池
//        Executors.newScheduledThreadPool();
        // 单线程线程池
//        Executors.newSingleThreadExecutor();

        // 区别:
        // 1 2不能得到返回值,3可以得到返回值
        // 1 2 3不能控制资源
        // 4可以控制资源,性能稳定(稳定第一)



        System.out.println("main end...");

    }

    public static class ThreadA extends Thread {

        @Override
        public void run() {
            System.out.println("当前线程: " + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果: " + i);
        }
    }

    public static class RunnableA implements Runnable {

        @Override
        public void run() {
            System.out.println("当前线程: " + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果: " + i);
        }
    }

    public static class CallableA implements Callable<Integer> {

        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程: " + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果: " + i);
            return i;
        }
    }
}
